using System;
using System.ComponentModel;
using System.Drawing;
using System.Globalization;
using System.Windows.Forms;

namespace OpenComposite.Base.Designer
{
	public class CollapsableSymbol : Symbol
	{
		#region Initialization
		public CollapsableSymbol()
		{
			init();
		}
		private void init()
		{
			this.BeginUpdate();

			_showCollapseButton = true;
			_useCustomCollapseClick = false;
			//
			// _btnCollapse
			//
			_btnCollapse = new CollapseButton();
			_btnCollapse.Click += new EventHandler(_btnCollapse_Click);

			// set properties
			this.IsCollapsed = false;
			this.CollapseSign = CollapseSign.PlusMinus;
			this.CollapseSignPosition = CollapseSignPosition.TopRight;
			
			this.CollapsedSize = new Size(70, 50);
			this.CollapsedBackColor = this.BackColor;
			this.CollapsedBackColor2 = this.BackColor2;
			this.CollapsedBorderColor = this.BorderColor;

			this.ExpandedSize = new Size(150, 100);
			this.ExpandedBackColor = Color.FromArgb(64, this.BackColor);
			this.ExpandedBackColor2 = Color.FromArgb(64, this.BackColor2);
			this.ExpandedBorderColor = this.BorderColor;

			setCollapseButtonSign(this.IsCollapsed);
			setCollapseButtonPosition(this.CollapseSignPosition);

			this.Controls.Add(_btnCollapse);

			this.EndUpdate();
		}
		#endregion

		#region Public Members

		#region Properties
		public bool ShowCollapseButton
		{
			get { return _showCollapseButton; }
			set
			{
				if ( _showCollapseButton != value ) {
					_showCollapseButton = value;
					this.CollapseButton.Visible = value;
				}
			}
		}
		public bool IsCollapsed
		{
			get { return _isCollapsed; }
			set
			{
				if ( _isCollapsed != value )
					doIsCollapsedChange(value);
			}
		}
		public bool UseCustomCollapseClick
		{
			get { return _useCustomCollapseClick; }
			set { _useCustomCollapseClick = value; }
		}

		public Size CollapsedSize
		{
			get { return _sizeCollapsed; }
			set
			{
				if ( _sizeCollapsed != value ) {
					_sizeCollapsed = value;
					setCollapsableSymbolValues(this.IsCollapsed);
				}
			}
		}
		public Size ExpandedSize
		{
			get { return _sizeExpanded; }
			set
			{
				if ( _sizeExpanded != value ) {
					_sizeExpanded = value;
					setCollapsableSymbolValues(this.IsCollapsed);
				}
			}
		}

		public Color CollapsedBackColor
		{
			get { return _backColorCollapsed; }
			set
			{
				if ( _backColorCollapsed != value ) {
					_backColorCollapsed = value;
					setCollapsableSymbolValues(this.IsCollapsed);
				}
			}
		}
		public Color CollapsedBackColor2
		{
			get { return _backColorCollapsed2; }
			set
			{
				if ( _backColorCollapsed2 != value ) {
					_backColorCollapsed2 = value;
					setCollapsableSymbolValues(this.IsCollapsed);
				}
			}
		}
		public Color CollapsedBorderColor
		{
			get { return _borderColorCollapsed; }
			set
			{
				if ( _borderColorCollapsed != value ) {
					_borderColorCollapsed = value;
					setCollapsableSymbolValues(this.IsCollapsed);
				}
			}
		}
		public Color ExpandedBackColor
		{
			get { return _backColorExpanded; }
			set
			{
				if ( _backColorExpanded != value ) {
					_backColorExpanded = value;
					setCollapsableSymbolValues(this.IsCollapsed);
				}
			}
		}
		public Color ExpandedBackColor2
		{
			get { return _backColorExpanded2; }
			set
			{
				if ( _backColorExpanded2 != value ) {
					_backColorExpanded2 = value;
					setCollapsableSymbolValues(this.IsCollapsed);
				}
			}
		}
		public Color ExpandedBorderColor
		{
			get { return _borderColorExpanded; }
			set
			{
				if ( _borderColorExpanded != value ) {
					_borderColorExpanded = value;
					setCollapsableSymbolValues(this.IsCollapsed);
				}
			}
		}

		public CollapseSign CollapseSign
		{
			get { return this.CollapseButton.CollapseSign; }
			set { this.CollapseButton.CollapseSign = value; }
		}
		public CollapseSignPosition CollapseSignPosition
		{
			get { return _positionCollapseSign; }
			set
			{
				if ( _positionCollapseSign != value ) {
					_positionCollapseSign = value;
					this.Refresh();
				}
			}
		}
		#endregion

		#region Events
		public event EventHandler CollapseButtonClick = null;
		public event EventHandler CustomCollapseButtonClick = null;
		public event CancelEventHandler Collapsing = null;
		public event EventHandler Collapsed = null;
		public event CancelEventHandler Expanding = null;
		public event EventHandler Expanded = null;
		#endregion

		#region Methods

		// overrided methods
		public override void PaintBackground(System.Windows.Forms.PaintEventArgs pe)
		{
			// default paintings
			base.PaintBackground(pe);
			#region DISABLED paint collapsed button border
			//Point[] points = null;
			//Rectangle bounds = this.GetPaintBounds();
			//int dxy = 20;
			//int x1 = (int)( bounds.Left + ( bounds.Width / 2.0f ) - ( dxy / 2.0f ) );
			//int y1 = (int)( bounds.Top + ( bounds.Height / 2.0f ) - ( dxy / 2.0f ) );
			//#region get points of border
			//switch ( this.CollapseSignPosition ) {
			//    case CollapseSignPosition.TopCenter:
			//        points = new Point[] {
			//            new Point(x1, bounds.Top),
			//            new Point(x1, bounds.Top + dxy),
			//            new Point(x1 + dxy, bounds.Top + dxy),
			//            new Point(x1 + dxy, bounds.Top)
			//        };
			//        break;
			//    case CollapseSignPosition.BottomCenter:
			//        points = new Point[] {
			//            new Point(x1, bounds.Bottom),
			//            new Point(x1, bounds.Bottom - dxy),
			//            new Point(x1 + dxy, bounds.Bottom - dxy),
			//            new Point(x1 + dxy, bounds.Bottom)
			//        };
			//        break;
			//    case CollapseSignPosition.LeftCenter:
			//        points = new Point[] {
			//            new Point(bounds.Left, y1),
			//            new Point(bounds.Left + dxy, y1),
			//            new Point(bounds.Left + dxy, y1 + dxy),
			//            new Point(bounds.Left, y1 + dxy)
			//        };
			//        break;
			//    case CollapseSignPosition.RightCenter:
			//        points = new Point[] {
			//            new Point(bounds.Right, y1),
			//            new Point(bounds.Right - dxy, y1),
			//            new Point(bounds.Right - dxy, y1 + dxy),
			//            new Point(bounds.Right, y1 + dxy)
			//        };
			//        break;
			//    case CollapseSignPosition.TopLeft:
			//        points = new Point[] {
			//            new Point(bounds.Left + dxy, bounds.Top),
			//            new Point(bounds.Left + dxy, bounds.Top + dxy),
			//            new Point(bounds.Left, bounds.Top + dxy)
			//        };
			//        break;
			//    case CollapseSignPosition.TopRight:
			//        points = new Point[] {
			//            new Point(bounds.Right - dxy, bounds.Top),
			//            new Point(bounds.Right - dxy, bounds.Top + dxy),
			//            new Point(bounds.Right, bounds.Top + dxy)
			//        };
			//        break;
			//    case CollapseSignPosition.BottomLeft:
			//        points = new Point[] {
			//            new Point(bounds.Left, bounds.Bottom - dxy),
			//            new Point(bounds.Left + dxy, bounds.Bottom - dxy),
			//            new Point(bounds.Left + dxy, bounds.Bottom)
			//        };
			//        break;
			//    case CollapseSignPosition.BottomRight:
			//        points = new Point[] {
			//            new Point(bounds.Right, bounds.Bottom - dxy),
			//            new Point(bounds.Right - dxy, bounds.Bottom - dxy),
			//            new Point(bounds.Right - dxy, bounds.Bottom)
			//        };
			//        break;
			//}
			//#endregion
			//using ( Pen pen = new Pen(this.BorderColor) ) {
			//    pe.Graphics.DrawLines(pen, points);
			//}
			#endregion
		}

		#endregion

		#endregion

		#region Protected Members

		#region Properties
		protected CollapseButton CollapseButton
		{
			get { return _btnCollapse; }
		}
		#endregion

		#region Methods
		// new methods
		protected virtual void OnCustomCollapseButtonClick()
		{
			EventHandler tmp = this.CustomCollapseButtonClick;
			if ( tmp != null )
				tmp(this, EventArgs.Empty);
		}
		protected virtual void OnCollapseButtonClick()
		{
			EventHandler tmp = this.CollapseButtonClick;
			if ( tmp != null )
				tmp(this, EventArgs.Empty);

			if ( this.DesignerViewControl.SelectedControls.Count > 0 ) {
				this.DesignerViewControl.SelectedControls.Clear();
				this.Select();
			}
			this.IsCollapsed = !this.IsCollapsed;
		}
		protected virtual void OnCollapsing(CancelEventArgs e)
		{
			CancelEventHandler tmp = this.Collapsing;
			if ( tmp != null )
				tmp(this, e);
		}
		protected virtual void OnCollapsed(EventArgs e)
		{
			EventHandler tmp = this.Collapsed;
			if ( tmp != null )
				tmp(this, e);
		}
		protected virtual void OnExpanding(CancelEventArgs e)
		{
			CancelEventHandler tmp = this.Expanding;
			if ( tmp != null )
				tmp(this, e);
		}
		protected virtual void OnExpanded(EventArgs e)
		{
			EventHandler tmp = this.Expanded;
			if ( tmp != null )
				tmp(this, e);
		}

		protected virtual void SetNameTextboxBounds(bool isCollapsed)
		{
			Rectangle rclient = this.ClientRectangle;
			if ( isCollapsed ) {
				this.NameTextBox.Bounds = new Rectangle(0, 0, rclient.Width, (int)( rclient.Height / 2 ));
				this.NameTextBox.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Bottom;
			} else {
				this.NameTextBox.Bounds = new Rectangle(0, 0, rclient.Width, 15);
				this.NameTextBox.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
			}
		}

		// overrided methods
		protected override void OnSizeChanged(EventArgs e)
		{
			if ( this.IsCollapsed ) {
				_sizeCollapsed = this.Size;
			} else {
				_sizeExpanded = this.Size;
			}
			base.OnSizeChanged(e);
		}
		protected override void OnControlAdded(DesignerControl ctrl)
		{
			base.OnControlAdded(ctrl);
			if ( this.IsCollapsed )
				ctrl.Visible = false;
		}
		protected override void OnVisibleChanged()
		{
			this.BeginUpdate();
			foreach ( DesignerControl dc in this.Controls ) {
				if ( !( this.IsCollapsed && this.Visible ) ||
					  ( dc == this.NameTextBox || dc == this.CollapseButton ) ) {
					dc.Visible = this.Visible;
					if ( dc == this.CollapseButton && !this.ShowCollapseButton )
						dc.Visible = false;
				}
			}
			this.EndUpdate();
		}

		protected override void PaintChildControls(System.Windows.Forms.PaintEventArgs pe)
		{
			base.PaintChildControls(pe);
		}

		protected override void ReadStandardProperties(System.Xml.XmlReader reader)
		{
			SizeConverter sc = new SizeConverter();
			BooleanConverter bc = new BooleanConverter();
			switch ( reader.Name ) {
				case "CollapsedSize":
					this.CollapsedSize = (Size)sc.ConvertFromString(null,
						CultureInfo.InvariantCulture,reader.ReadString().Replace(';',','));
					break;
				case "ExpandedSize":
					this.ExpandedSize = (Size)sc.ConvertFromString(null,
						CultureInfo.InvariantCulture, reader.ReadString().Replace(';', ','));
					break;
				case "IsCollapsed": {
						bool isCollapsed = false;
						if ( bool.TryParse(reader.ReadString(), out isCollapsed) ) {
							//this.IsCollapsed = isCollapsed;
							_isCollapsed = isCollapsed;
							setCollapsableSymbolValues(_isCollapsed);
							setCollapseButtonSign(_isCollapsed);
							SetNameTextboxBounds(_isCollapsed);
						}
					}
					break;
				case "ShowCollapseButton":
					this.ShowCollapseButton = (bool)bc.ConvertFromString(reader.ReadString());
					break;
				case "UseCustomCollapseClick":
					this.UseCustomCollapseClick = (bool)bc.ConvertFromString(reader.ReadString());
					break;
				default:
					base.ReadStandardProperties(reader);
					break;
			}
		}
		protected override void WriteStandardProperties(System.Xml.XmlWriter writer)
		{
			base.WriteStandardProperties(writer);

			SizeConverter sc = new SizeConverter();
			BooleanConverter bc = new BooleanConverter();

			writer.WriteElementString("CollapsedSize", sc.ConvertToString(this.CollapsedSize));
			writer.WriteElementString("ExpandedSize", sc.ConvertToString(this.ExpandedSize));
			writer.WriteElementString("IsCollapsed", this.IsCollapsed.ToString());
			writer.WriteElementString("ShowCollapseButton", bc.ConvertToString(this.ShowCollapseButton));
			writer.WriteElementString("UseCustomCollapseClick", bc.ConvertToString(this.UseCustomCollapseClick));
		}
		#endregion

		#endregion

		#region Private Members

		#region Variables
		private bool _isCollapsed;
		private bool _showCollapseButton;
		private bool _useCustomCollapseClick;

		private Size _sizeCollapsed;
		private Size _sizeExpanded;
		//private Size _sizeCollapseButton;

		private Color _backColorCollapsed;
		private Color _backColorCollapsed2;
		private Color _borderColorCollapsed;
		private Color _backColorExpanded;
		private Color _backColorExpanded2;
		private Color _borderColorExpanded;

		private CollapseButton _btnCollapse;
		private CollapseSignPosition _positionCollapseSign;
		#endregion

		#region Methods
		private void doIsCollapsedChange(bool newIsCollapsed)
		{
			this.BeginUpdate();

			CancelEventArgs cancelArgs = new CancelEventArgs();
			if ( newIsCollapsed )
				OnCollapsing(cancelArgs);
			else
				OnExpanding(cancelArgs);

			if ( !cancelArgs.Cancel ) {
				_isCollapsed = newIsCollapsed;

				setChildControlsVisible(_isCollapsed);
				setCollapsableSymbolValues(_isCollapsed);
				setCollapseButtonSign(_isCollapsed);
				SetNameTextboxBounds(_isCollapsed);

				if ( _isCollapsed )
					OnCollapsed(new EventArgs());
				else
					OnExpanded(new EventArgs());
			}

			this.EndUpdate();
		}

		private void setChildControlsVisible(bool isCollapsed)
		{
			foreach ( DesignerControl dc in this.Controls ) {
				if ( dc != this.NameTextBox && dc != this.CollapseButton ) {
					dc.Visible = !isCollapsed;
				}
			}
		}
		private void setCollapsableSymbolValues(bool isCollapsed)
		{
			this.BeginUpdate();

			this.Size = ( isCollapsed ? _sizeCollapsed : _sizeExpanded );

			this.BorderColor = ( isCollapsed ? _borderColorCollapsed : _borderColorExpanded );
			this.BackColor = ( isCollapsed ? _backColorCollapsed : _backColorExpanded );
			this.BackColor2 = ( isCollapsed ? _backColorCollapsed2 : _backColorExpanded2 );

			this.EndUpdate();
		}

		private void setCollapseButtonSign(bool isCollapsed)
		{
			this.CollapseButton.IsCollapsed = isCollapsed;
		}
		private void setCollapseButtonPosition(CollapseSignPosition pos)
		{
			Rectangle bounds = this.ClientRectangle;
			switch ( pos ) {
				case CollapseSignPosition.TopCenter:
					this.CollapseButton.Location = new Point(
						(int)( ( bounds.Width / 2.0f ) - ( this.CollapseButton.Width / 2.0f ) ), 0);
					this.CollapseButton.Anchor = System.Windows.Forms.AnchorStyles.Top;
					break;
				case CollapseSignPosition.BottomCenter:
					this.CollapseButton.Location = new Point(
						(int)( ( bounds.Width / 2.0f ) - ( this.CollapseButton.Width / 2.0f ) ),
						bounds.Height - this.CollapseButton.Height);
					this.CollapseButton.Anchor = System.Windows.Forms.AnchorStyles.Bottom;
					break;
				case CollapseSignPosition.LeftCenter:
					this.CollapseButton.Location = new Point(
						0, (int)( ( bounds.Height / 2.0f ) - ( this.CollapseButton.Height / 2.0f ) ));
					this.CollapseButton.Anchor = System.Windows.Forms.AnchorStyles.Left;
					break;
				case CollapseSignPosition.RightCenter:
					this.CollapseButton.Location = new Point(
						bounds.Width - this.CollapseButton.Width,
						(int)( ( bounds.Height / 2.0f ) - ( this.CollapseButton.Height / 2.0f ) ));
					this.CollapseButton.Anchor = System.Windows.Forms.AnchorStyles.Right;
					break;
				case CollapseSignPosition.TopLeft:
					this.CollapseButton.Location = new Point(0, 0);
					this.CollapseButton.Anchor = System.Windows.Forms.AnchorStyles.Top |
												 System.Windows.Forms.AnchorStyles.Left;
					break;
				case CollapseSignPosition.TopRight:
					this.CollapseButton.Location = new Point(bounds.Width - this.CollapseButton.Width, 0);
					this.CollapseButton.Anchor = System.Windows.Forms.AnchorStyles.Top |
												 System.Windows.Forms.AnchorStyles.Right;
					break;
				case CollapseSignPosition.BottomLeft:
					this.CollapseButton.Location = new Point(0,	bounds.Height - this.CollapseButton.Height);
					this.CollapseButton.Anchor = System.Windows.Forms.AnchorStyles.Bottom |
												 System.Windows.Forms.AnchorStyles.Left;
					break;
				case CollapseSignPosition.BottomRight:
					this.CollapseButton.Location = new Point(
						bounds.Width - this.CollapseButton.Width,
						bounds.Height - this.CollapseButton.Height);
					this.CollapseButton.Anchor = System.Windows.Forms.AnchorStyles.Bottom |
												 System.Windows.Forms.AnchorStyles.Right;
					break;
			}
		}
		#endregion

		#region Event Handlers
		private void _btnCollapse_Click(object sender, EventArgs e)
		{
			if ( _useCustomCollapseClick )
				OnCustomCollapseButtonClick();
			else
				OnCollapseButtonClick();
		}
		#endregion

		#endregion

	}
	#region Enum: CollapseSignPosition
	public enum CollapseSignPosition
	{
		TopCenter,
		BottomCenter,
		LeftCenter,
		RightCenter,
		TopLeft,
		TopRight,
		BottomLeft,
		BottomRight
	}
	#endregion

}
